// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#include "mk_header.h"
#include "mk_cegui_renderer.h"
#include "mk_engine.h"
#include "mk_error.h"
#include "mk_painter.h"
#include "mk_render_device.h"
#include "mk_texture.h"

namespace MK3DE
{
	CCEGUIRenderer::CCEGUIRenderer() :
		_queueing(false),
		_maxTextureSize(0)
	{

	}

	CCEGUIRenderer::~CCEGUIRenderer()
	{
		destroyAllTextures();
	}

	BOOL CCEGUIRenderer::Init()
	{
		CRenderDevice* rd = GetEngine()->GetRenderDevice();
		_maxTextureSize = rd->GetMaxTextureSize();

		DWORD x, y, w, h;
		float minZ, maxZ;
		rd->GetViewport(x, y, w, h, minZ, maxZ);
		_displayArea.d_left = 0;
		_displayArea.d_top = 0;
		_displayArea.setWidth((float)w);
		_displayArea.setHeight((float)h);

		return TRUE;
	}

	void CCEGUIRenderer::addQuad(const CEGUI::Rect& dest_rect, float z, const CEGUI::Texture* tex, const CEGUI::Rect& texture_rect, const CEGUI::ColourRect& colours, CEGUI::QuadSplitMode quad_split_mode)
	{
		__Quad quad;
		quad.rcTarget.SetRect(dest_rect.d_left, dest_rect.d_top, dest_rect.d_right, dest_rect.d_bottom);
		quad.z = z;
		quad.tex = ((CCEGUITexture*)tex)->_GetTexture();
		quad.rcTex.SetRect(texture_rect.d_left, texture_rect.d_top, texture_rect.d_right, texture_rect.d_bottom);
		quad.color.leftTop = colours.d_top_left.getARGB();
		quad.color.rightTop = colours.d_top_right.getARGB();
		quad.color.leftBottom = colours.d_bottom_left.getARGB();
		quad.color.rightBottom = colours.d_bottom_right.getARGB();

		if (_queueing)
			_renderQuadList.push_back(quad);
		else
		{
			CPainter* painter = GetEngine()->GetPainter();
			painter->DrawImageSub2D(quad.rcTarget, quad.rcTex, quad.color, quad.tex);
			painter->Flush();
		}
	}

	void CCEGUIRenderer::doRender()
	{
		CPainter* painter = GetEngine()->GetPainter();
		RenderQuadList::iterator i = _renderQuadList.begin();
		while (i != _renderQuadList.end())
		{
			__Quad& quad = *i;
			painter->DrawImageSub2D(quad.rcTarget, quad.rcTex, quad.color, quad.tex);

			++i;
		}

		painter->Flush();
	}

	void CCEGUIRenderer::clearRenderList()
	{
		_renderQuadList.clear();
	}

	CEGUI::Texture* CCEGUIRenderer::createTexture(void)
	{
		CCEGUITexture* tex = new CCEGUITexture(this);
		MK_PROCESS_ERROR(tex);

		_textureList.push_back(tex);
	Exit0:
		return tex;
	}

	CEGUI::Texture* CCEGUIRenderer::createTexture(const CEGUI::String& filename, const CEGUI::String& resourceGroup)
	{
		BOOL ret = FALSE;
		CCEGUITexture* tex = new CCEGUITexture(this);
		if (!tex)
			return NULL;

		try
		{
			tex->loadFromFile(filename, resourceGroup);
		}
		catch (CEGUI::RendererException&)
		{
			delete tex;
			throw;
		}

		_textureList.push_back(tex);
		return tex;
	}

	CEGUI::Texture* CCEGUIRenderer::createTexture(float size)
	{
		BOOL ret = FALSE;
		CCEGUITexture* tex = new CCEGUITexture(this);
		MK_PROCESS_ERROR(tex);

		ret = tex->_CreateTexture((DWORD)size);
		MK_PROCESS_ERROR(ret);

		_textureList.push_back(tex);

		ret = TRUE;
	Exit0:
		if (!ret)
			SAFE_DELETE(tex);

		return tex;
	}

	void CCEGUIRenderer::destroyTexture(CEGUI::Texture* texture)
	{
		if (!texture)
			return;

		TextureList::iterator i = _textureList.begin();
		while (i != _textureList.end())
		{
			CCEGUITexture* t = *i;
			if (texture == t)
			{
				SAFE_DELETE(t);
				_textureList.erase(i);
				break;
			}

			++i;
		}
	}

	void CCEGUIRenderer::destroyAllTextures()
	{
		TextureList::iterator i = _textureList.begin();
		while (i != _textureList.end())
		{
			CCEGUITexture* tex = *i;
			SAFE_DELETE(tex);
			++i;
		}

		_textureList.clear();
	}


}